package org.upt.dcda.webservices;

import java.util.ArrayList;
import java.util.List;

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.QueryParam;

import org.upt.dcda.BookManagerBeanRemote;
import org.upt.dcda.SearchManagerBeanRemote;
import org.upt.dcda.db.BookEntity;
import org.upt.dcda.db.BookReviewEntity;

@Path("/services/books/")
public class BookServices extends CommonService
{

	private String booksToJson(List<BookEntity> books)
	{
		List<Book> result = new ArrayList<Book>();
		for (BookEntity book : books)
		{
			final Book buk = new Book(book.getBookId(), book.getBookTitle(),
					book.getBookPrice(), book.getAuthor().getAuthorName(),
					book.getBookQuantity());
			result.add(buk);
		}
		return gson.toJson(result);
	}

	@GET
	@Path("list")
	public String list() throws Exception
	{
		SearchManagerBeanRemote search;
		try
		{
			search = getSearchManagerBean();
			return booksToJson(search.browseAll());
		}
		catch (Throwable t)
		{
			logger.error("Caught " + t.getClass() + ": " + t, t);
			throw new Exception("Cannot complete request");
		}
	}

	@GET
	@Path("listByTag")
	public String listByTag(@QueryParam("tags") List<String> tags)
			throws Exception
	{
		logger.debug("-> listByTag(tags = " + tags + ")");

		try
		{
			final SearchManagerBeanRemote search = getSearchManagerBean();
			String[] tagArray = tags.toArray(new String[tags.size()]);
			final String result = booksToJson(tags.isEmpty() ? search
					.browseAll() : search.browse(tagArray));

			logger.debug("<- listByTag(tags = " + tags + ")");
			return result;
		}
		catch (Throwable t)
		{
			logger.error("Caught " + t.getClass() + ": " + t, t);
			throw new Exception("Cannot complete request");
		}
	}

	@GET
	@Path("searchByKeywords")
	public String search(@QueryParam("key") String key) throws Exception
	{

		logger.debug("-> searchByKeywords(key = " + key + ")");

		try
		{
			final SearchManagerBeanRemote search = getSearchManagerBean();
			final String result = booksToJson(search.search(key));

			return result;
		}
		catch (Throwable t)
		{
			logger.error("Caught " + t.getClass() + ": " + t, t);
			throw new Exception("Cannot complete request");
		}

	}

	@GET
	@Path("getInfo")
	public String getInfo(@QueryParam("id") int bookId) throws Exception
	{
		BookManagerBeanRemote bookMan;
		try
		{
			bookMan = getBookManagerBean();
			BookEntity book = bookMan.getBookById(bookId);
			DescribedBook descBook = new DescribedBook(book.getBookId(),
					book.getBookTitle(), book.getBookPrice(), book.getAuthor()
							.getAuthorName(), book.getBookQuantity(),
					book.getBookDescription(), book.getAuthor().getAuthorId());
			return gson.toJson(descBook);
		}
		catch (Throwable t)
		{
			logger.error("Caught " + t.getClass() + ": " + t, t);
			throw new Exception("Cannot complete request");
		}
	}

	@GET
	@Path("getBookReview")
	public String getBookReview(@QueryParam("id") int bookId) throws Exception
	{
		BookManagerBeanRemote bookMan;
		try
		{
			bookMan = getBookManagerBean();
			List<BookReviewEntity> reviewList = bookMan
					.getBookReviewByBookId(bookId);
			List<BookReview> result = new ArrayList<BookReview>();
			for (BookReviewEntity bre : reviewList)
			{
				result.add(new BookReview(bre.getBookreviewId(), bre
						.getBookreviewContent(), bre.getBookreviewMark(), bre
						.getUser().getUserEmail()));
			}

			return gson.toJson(result);
		}
		catch (Throwable t)
		{
			logger.error("Caught " + t.getClass() + ": " + t, t);
			throw new Exception("Cannot complete request");
		}
	}

	private class Book
	{

		@SuppressWarnings("unused")
		public final int	id;

		@SuppressWarnings("unused")
		public final String	name;

		@SuppressWarnings("unused")
		public final int	price;

		@SuppressWarnings("unused")
		public final String	author;

		@SuppressWarnings("unused")
		public final int	quantity;

		public Book(int id, String name, int price, String author, int quantity)
		{
			this.id = id;
			this.name = name;
			this.price = price;
			this.author = author;
			this.quantity = quantity;
		}
	}

	private class DescribedBook extends Book
	{

		@SuppressWarnings("unused")
		public final String	description;

		@SuppressWarnings("unused")
		public final int	authorId;

		public DescribedBook(int id, String name, int price, String author,
				int quantity, String description, int authorId)
		{
			super(id, name, price, author, quantity);
			this.description = description;
			this.authorId = authorId;
		}

	}

	private class BookReview
	{

		@SuppressWarnings("unused")
		public final int	bookReviewId;

		@SuppressWarnings("unused")
		public final String	content;

		@SuppressWarnings("unused")
		public final int	mark;

		@SuppressWarnings("unused")
		public final String	username;

		public BookReview(int bookReviewId, String content, int mark,
				String username)
		{
			this.bookReviewId = bookReviewId;
			this.content = content;
			this.mark = mark;
			this.username = username;
		}
	}

}
